home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
ls.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
23KB
|
807 lines
/* ls - list files Author: Peter Housel */
/*@*Introduction.
* This file is part of \fIls\fP for Minix. It was written in the spring
* of 1989 by Peter S. Housel. This program is in the public domain and may
* be redistributed without restriction. As such, no warranty of any kind
* is provided.
* .PP
* The following changes to the program have been made:
* .IP \(bu
* Version 1.1 - removed references to \fB\-q\fP option, added |ONECOLUMN|
* and other compile-time options.
*/
/*@ \fILs\fP is a version of standard Minix directory listing program. Because
* it use so often used, it should be as fast as possible. It should be
* somewhat "featureful" (Rob Pike nonwithstanding), but not in a way
* that interferes with its use as a "software tool." It should take
* up a small to medium amount of memory.
* .PP
* The program should be compiled using:
* .nf
* \fBcc -o ls -D_MINIX -D_POSIX_SOURCE ls.c
* chmem =4096 ls\fP
* or
* \fBcc -o ls -DATARI_ST ls.c\fP
* .fi
* If you do not want multi-column listings to be the default when
* standard output is a tty, define |ONECOLUMN| (by adding
* \fB\-DONECOLUMN\fP to the compile flags). Similarly, |NFILE|,
* |STRINGSPACE|, and |LINEWIDTH| can be changed with appropriate
* predefines.
*/
#define ONECOLUMN /* default is 1 column listings */
#define major(x) ( (x>>8) & 0377)
#define minor(x) (x & 0377)
/*@ Since \fIls\fP has to know a lot about files, there are quite a few
* headers to include.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <limits.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <stdio.h>
extern int errno;
/*@ |DOTDIR()| determines whether or not a given |name| is one of the
* special directory files "." or "..".
*/
#define DOTDIR(name) \
(name[0] == '.' \
&& (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
/*@ We use |getopt()| to parse the command-line flag arguments. This
* annoys some people who are used to the (BSD pre-Tahoe release)
* "infinte args \fIls\fP" that doesn't complain about anything.
*/
extern int getopt( /* int argc, char **argv, char *optstring */ );
extern char *optarg;
extern int optind;
/*@ It may be necessary to |stat()| each file that is listed.
* The toplevel files (specified by the arguments) will need to be, to
* determine which ones are directories. Several of the options will
* make it necessary to have the |stat()| information (the \fB\-l\fP and
* \fB\-R\fP options, for example), and we will turn on |stateach|
* later on if any of these are set.
*/
int stateach;
/*@ \fILs\fP takes quite a few options: .IP \fB\-l\fP
* Print in "long listing" format. Sets |flags_l|, unsets |flags_C|.
* .IP \fB\-g\fP
* Include the group ownership along with the user ownership in the long
* format listing. Sets |flags_g|.
* .IP \fB\-t\fP
* Sort the listing by the modification time, with most recent times
* printed first. Sets |flags_t|.
* .IP \fB\-a\fP
* Include all files. By default, files whose names begin with "." are not
* included. Sets |flags_a|.
* .IP \fB\-A\fP
* Include all files, even those beginning with ".", except for "." and "..".
* This flag is automatically turned on for the superuser. Sets |flags_A|.
* .IP \fB\-s\fP
* Print the size of the file (in kilobytes) with each file. Sets |flags_s|.
* .IP \fB\-d\fP
* List named directories explicitly instead of their contents. Sets
* |flags_d|.
* .IP \fB\-r\fP
* Sort the listing in reverse order. Sets |flags_r|.
* .IP \fB\-u\fP
* Use the file access time instead of the modification time in the listings
* (\fB\-l\fP option) and/or as the sort key (\fB\-t\fP option). Sets
* |flags_u|. \fI(Currently ineffectual in Minix.)\fP
* .IP \fB\-c\fP
* Like \fB\-u\fP, except that the inode change time is used instead.
* Sets |flags_c|.
* .IP \fB\-i\fP
* Print the file's inode number with each file. Sets |flags_i|.
* .IP \fB\-f\fP
* Force the named files to be interpreted as directories, whether they
* are or not. (Actually, the POSIX-type directory routines cause problems
* with this. They reqire that the file be a directory.) Sets |flags_f|
* and |flags_a|, and unsets |flags_l|,
* |flags_t|, |flags_s|, and |flags_r|.
* .IP \fB\-F\fP
* After the filenames of directories, print "/". After executable files,
* print "*". Sets |flags_F|.
* .IP \fB\-R\fP
* Recursively print each subdirectory. Sets |flags_R|.
* .IP \fB\-1\fP
* Print in "one-column" format instead of columnar format. This is the
* default if standard output is not a tty. Unsets |flags_C|.
* .IP \fB\-C\fP
* Print in columnar format. This is the default if standard output is
* a tty, provided |ONECOLUMN| has not been defined. Sets |flags_C|.
*/
#define VALID_FLAGS "lgtaAsdrucifFR1C"
int flags_l, flags_g, flags_t, flags_a, flags_A, flags_s, flags_d, flags_r, flags_u, flags_c, flags_i, flags_f, flags_F, flags_R, flags_C;
/*@ */
main(argc, argv)
int argc;
char *argv[];
{
void add_args( /* int argc; char **argv; */ );
void listall( /* void */ );
int c; /* option character */
#ifdef noperprintf
noperprintf(stdout);
#endif
#ifndef ONECOLUMN
if (isatty(1)) flags_C = 1;
#endif
while ((c = getopt(argc, argv, VALID_FLAGS)) != EOF) {
switch (c) {
case 'l': flags_l = 1; break;
case 'g': flags_g = 1; break;
case 't': flags_t = 1; break;
case 'a': flags_a = 1; break;
case 'A': flags_A = 1; break;
case 's': flags_s = 1; break;
case 'd': flags_d = 1; break;
case 'r': flags_r = 1; break;
case 'u': flags_u = 1; break;
case 'c': flags_c = 1; break;
case 'i': flags_i = 1; break;
case 'f': flags_f = 1; break;
case 'F': flags_F = 1; break;
case 'R': flags_R = 1; break;
case '1': flags_C = 0; break;
case 'C': flags_C = 1; break;
case '?':
fprintf(stderr, "Usage: ls -%s [file ...]\n",
VALID_FLAGS);
exit(1);
}
}
if (flags_f) {
flags_l = flags_t = flags_s = flags_r = 0;
flags_a = 1;
}
if (flags_l || flags_s || flags_i) flags_C = 0;
flags_r = flags_r ? -1 : 1; /* multiplier for comparisons */
if (geteuid() == 0 && !flags_a) flags_A = 1;
stateach = !flags_f;
add_args(argc - optind + 1, argv + optind - 1);
stateach = !flags_f && (flags_l || flags_t || flags_s || flags_i
|| flags_F || flags_R);
listall();
exit(0);
}
/*@* The files table.
* The |struct lsfile| structure is the main data structure used by
* \fIls\fP. The |files| array is an array of these structures, with
* each entry representing one file to be listed by the program.
* The |f_stat| field is the result of a |stat()| call on the file, if
* one has been done. The |f_name| field points to the filename, either
* directly to the command-line argument, or to a copy in string space
* of a name read from a directory. The |f_parent| field points to the
* parent directory of a file, so that the entire relative pathname
* can be constructed using the |pathname()| function below.
* .PP
* There are at most |NFILE| entries in the staticaly-allocated table.
* Entries are added as a directory is read in, and removed when the
* listing of that directory is done. The |filep| variable is used to
* point to the next free entry.
*/
#ifndef NFILE
#define NFILE 512
#endif
struct lsfile {
struct stat f_stat; /* file information from inode */
char *f_name; /* file name */
struct lsfile *f_parent; /* parent directory, if any */
};
struct lsfile files[NFILE];
struct lsfile *filep = files;
/*@ When a directory is sorted, the time spent exchanging entries is reduced
* by exchanging pointers to entries instead of the entries themselves.
* When a listing is printed, the file table entries are accessed
* indirectly through |sortindex| entries.
*/
struct lsfile *sortindex[NFILE];
/*@ The string area is used to store filenames read in from directories,
* as well as the lines of output for columnar listings. Like the file
* table, space in the string area is deallocated when it is no longer
* needed.
*/
#ifndef STRINGSPACE
#define STRINGSPACE 8192
#endif
char strings[STRINGSPACE];
char *stringp = strings;
/*@ The |AD